//二次封装axios模块，包含拦截器等信息
import axios from 'axios'
import FileSaver from 'file-saver';
import config from './config'
import router from '../router'
import {Message} from 'element-ui'

/**
 * 检查是否文件
 */
function checkFileGetSuccess(response) {
  return new Promise((resolve) => {
    let blob = new Blob([response.data]);
    let reader = new FileReader();
    reader.readAsText(blob, 'utf-8');
    reader.onload = function () {
      try {
        resolve(JSON.parse(reader.result));
      } catch (err) {
        resolve({});
      }
    };
  });
}

/**
 * 下载文件
 */
function saveFile(response) {
  let blob = new Blob([response.data]);
  let fileName = Math.random() + '.xlsx';
  let header = 'content-disposition';
  if (response.headers[header]) {
    const suffixName = response.headers[header].split('.')[1];
    if (suffixName === 'zip') {
      blob = new Blob([response.data], {
        type: 'application/zip'
      });
    }
    fileName = response.headers[header].split('filename=')[1];
    try {
      fileName = decodeURIComponent(fileName || '下载文件');
    } catch (error) {
      console.log(error);
      throw error;
    }
  }
  FileSaver.saveAs(blob, fileName);
}

export default function $axios(options) {
  return new Promise((resolve, reject) => {
    const instance = axios.create({
      baseURL: config.baseUrl,
      headers: config.headers,
      timeout: config.timeout,
      withCredentials: config.withCredentials
    });
    //request请求拦截器
    instance.interceptors.request.use(
      config => {
        let token = localStorage.getItem('token');
        //发送请求时携带token
        if (token) {
          config.headers.token = token;
        } else {
          //重定向到登录页
          router.push('/login');
        }
        return config;
      },
      error => {
        //发生错误时
        //判断请求超时
        if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
          Message.error('TimeOut，请求超时');
        }
        //需要重定向到错误页面
        const errorInfo = error.response;
        console.log(errorInfo);
        if (errorInfo) {
          // 页面那边catch的时候就能拿到详细的错误信息,看最下边的Promise.reject
          error = errorInfo.data;
          // 404 403 500 ...
          const errorStatus = errorInfo.status;
          router.push({
            path: `/error/${errorStatus}`
          });
        }
        // 在调用的那边可以拿到(catch)你想返回的错误信息
        return Promise.reject(error);
      }
    );
    // response响应拦截器
    instance.interceptors.response.use(
      async (response, reject) => {
        const responseType = response.request.responseType;
        if (['arraybuffer'].includes(responseType)) {
          // 检查是否是文件流
          let checked = await checkFileGetSuccess(response);
          // 成功请求的文件流，没有code，失败时把 res.data 转成 json 形式
          if (!checked.code) {
            response.data.code = 200;
            response.data.data = checked;
            saveFile(response);
            return Promise.reject(response);
          }
        }
        let res = response.data;
        // token过期，重返登录界面
        if (res.code === 401) {
          Message.error('登录已过期，即将跳转到登录页！');
          setTimeout(() => {
            localStorage.clear();
            router.replace('/');
          }, 1500);
        }
        if (res.code !== 200) {
          reject(res.message)
        }
        return res;
      },
      error => {
        if (error && error.response) {
          switch (error.response.status) {
            case 400:
              error.message = '请求错误';
              break;
            case 401:
              error.message = '登录过期，请重新登录';
              break;
            case 403:
              error.message = '权限不足，请联系管理员';
              break;
            case 404:
              error.message = `请求地址出错: ${error.response.config.url}`;
              break;
            case 408:
              error.message = '请求超时';
              break;
            case 500:
              error.message = '服务器内部错误';
              break;
            case 501:
              error.message = '服务未实现';
              break;
            case 502:
              error.message = '网关错误';
              break;
            case 503:
              error.message = '服务不可用';
              break;
            case 504:
              error.message = '网关超时';
              break;
            case 505:
              error.message = 'HTTP版本不受支持';
              break;
            default:
              error.message = '未知错误';
          }
        }
        //返回接口返回的错误信息
        return Promise.reject(error);
      }
    );
    //请求处理
    instance(options).then(res => {
      resolve(res);
      return false;
    }).catch(error => {
      reject(error);
    })
  });
}
